﻿/***********************************************************
Copyright © 2015 Howyoung.
************************************************************
You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty.
************************************************************
您可以对所收受的本程序源代码，无论以何种媒介，复制与发布其完
整的复制物，然而您必须以显著及适当的方式在每一份复制物上发布
适当的著作权标示及无担保声明。
***********************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace MinecraftSavesBackup
{
    public partial class Main : Form
    {
        public bool fileChanged = false;
        BackupIco BackupIco = new BackupIco();

        public Main()
        {
            InitializeComponent();
        }

        private void Main_Load(object sender, EventArgs e)
        {
            //加载个性化设置
            if (Properties.Settings.Default.ForeColor == Color.White)
            {
                percentLabel.ForeColor = Color.White;
                stateLabel.ForeColor = Color.White;
                startLabel.ForeColor = Color.White;
                settingsLabel.ForeColor = Color.White;
                backupLabel.ForeColor = Color.White;
                viewLabel.ForeColor = Color.White;
                helpLabel.ForeColor = Color.White;
                aboutLabel.ForeColor = Color.White;
                startPictureBox.Image = Properties.Resources.startGameWhite;
                settingsPictureBox.Image = Properties.Resources.settingsWhite;
                backupPictureBox.Image = Properties.Resources.backupWhite;
                viewPictureBox.Image = Properties.Resources.viewBackupWhite;
                helpPictureBox.Image = Properties.Resources.helpWhite;
                aboutPictureBox.Image = Properties.Resources.aboutWhite;
            }
            else
            {
                percentLabel.ForeColor = Color.Black;
                stateLabel.ForeColor = Color.Black;
                startLabel.ForeColor = Color.Black;
                settingsLabel.ForeColor = Color.Black;
                backupLabel.ForeColor = Color.Black;
                viewLabel.ForeColor = Color.Black;
                helpLabel.ForeColor = Color.Black;
                aboutLabel.ForeColor = Color.Black;
                startPictureBox.Image = Properties.Resources.startGameBlack;
                settingsPictureBox.Image = Properties.Resources.settingsBlack;
                backupPictureBox.Image = Properties.Resources.backupBlack;
                viewPictureBox.Image = Properties.Resources.viewBackupBlack;
                helpPictureBox.Image = Properties.Resources.helpBlack;
                aboutPictureBox.Image = Properties.Resources.aboutBlack;
            }
            statePanel.BackColor = Properties.Settings.Default.BackColor;
            startPanel.BackColor = Properties.Settings.Default.BackColor;
            settingsPanel.BackColor = Properties.Settings.Default.BackColor;
            backupPanel.BackColor = Properties.Settings.Default.BackColor;
            viewPanel.BackColor = Properties.Settings.Default.BackColor;
            helpPanel.BackColor = Properties.Settings.Default.BackColor;
            aboutPanel.BackColor = Properties.Settings.Default.BackColor;
            //加载自动备份设置
            automaticBackupTimer.Enabled = Properties.Settings.Default.AutomaticBackup && Properties.Settings.Default.AutomaticBackupByTime;
            automaticBackupTimer.Interval = Properties.Settings.Default.AutomaticBackupTime;
            //检测是否需要备份
            if (Properties.Settings.Default.AutomaticBackup && !Properties.Settings.Default.AutomaticBackupByTime && Properties.Settings.Default.AutomaticBackupIfChanged)
            {
                FindDifference();
            }
            else if (Properties.Settings.Default.AutomaticBackup && !Properties.Settings.Default.AutomaticBackupByTime && !Properties.Settings.Default.AutomaticBackupIfChanged)
            {
                Backup();
            }
        }

        private double GetDirectorySize(string directoryName)
        {
            try
            {
                double size = 0;
                DirectoryInfo directory = new DirectoryInfo(directoryName);
                //遍历文件
                foreach (FileInfo files in directory.GetFiles("*", SearchOption.AllDirectories))
                {
                    size = size + files.Length;
                }
                size = size / 1024 / 1024;//换算为MB
                return size;
            }
            catch (Exception ex)
            {
                HandlingErrors.Record(ex);
                return 0;
            }
        }

        private void Backup()//备份过程
        {
            try
            {
                //禁用按钮，显示状态
                if (Properties.Settings.Default.ShowBackupIco)
                {
                    BackupIco.Show();
                }
                backupLabel.Text = "正在备份...";
                stateLabel.Text = "正在备份...";
                percentLabel.Text = "0%";
                等待下一次备份0ToolStripMenuItem.Text = "正在备份(0%)";
                backupPanel.Enabled = false;
                backupBackgroundWorker.RunWorkerAsync();
            }
            catch (Exception ex)
            {
                notifyIcon.ShowBalloonTip(5000, "Minecraft 存档备份 - 备份时出现错误", ex.Message, ToolTipIcon.Error);
                HandlingErrors.Record(ex);
            }
        }

        private void FindDifference()//查找文件变化过程
        {
            try
            {
                if (Properties.Settings.Default.ShowBackupIco)
                {
                    BackupIco.Show();
                }
                backupLabel.Text = "查找文件变化...";
                stateLabel.Text = "正在查找文件变化...";
                percentLabel.Text = "0%";
                等待下一次备份0ToolStripMenuItem.Text = "正在查找文件变化(0%)";
                backupPanel.Enabled = false;
                findDifferenceBackgroundWorker.RunWorkerAsync();
            }
            catch (Exception ex)
            {
                HandlingErrors.Record(ex);
            }
        }

        private void PanelMouseEnter(Panel panel)
        {
            try
            {
                //加深或变淡20点颜色
                int r, g, b;
                r = Properties.Settings.Default.BackColor.R;
                g = Properties.Settings.Default.BackColor.G;
                b = Properties.Settings.Default.BackColor.B;
                if (r + g + b > 255 * 3 / 2)
                {
                    //浅色，变深
                    r = r - 20;
                    g = g - 20;
                    b = b - 20;
                    if (r < 0) r = 0;
                    if (g < 0) g = 0;
                    if (b < 0) b = 0;
                }
                else
                {
                    //深色，变浅
                    r = r + 20;
                    g = g + 20;
                    b = b + 20;
                    if (r > 255) r = 255;
                    if (g > 255) g = 255;
                    if (b > 255) b = 255;
                }
                panel.BackColor = Color.FromArgb(r, g, b);
            }
            catch (Exception ex)
            {
                HandlingErrors.Record(ex);
            }
        }
        //----窗体效果Start----
        //----鼠标移过效果Start----
        private void startPanel_MouseEnter(object sender, EventArgs e)
        {
            PanelMouseEnter(startPanel);
        }

        private void startPanel_MouseLeave(object sender, EventArgs e)
        {
            startPanel.BackColor = Properties.Settings.Default.BackColor;
        }

        private void settingsPanel_MouseEnter(object sender, EventArgs e)
        {
            PanelMouseEnter(settingsPanel);
        }

        private void settingsPanel_MouseLeave(object sender, EventArgs e)
        {
            settingsPanel.BackColor = Properties.Settings.Default.BackColor;
        }

        private void backupPanel_MouseEnter(object sender, EventArgs e)
        {
            PanelMouseEnter(backupPanel);
        }

        private void backupPanel_MouseLeave(object sender, EventArgs e)
        {
            backupPanel.BackColor = Properties.Settings.Default.BackColor;
        }

        private void viewPanel_MouseEnter(object sender, EventArgs e)
        {
            PanelMouseEnter(viewPanel);
        }

        private void viewPanel_MouseLeave(object sender, EventArgs e)
        {
            viewPanel.BackColor = Properties.Settings.Default.BackColor;
        }

        private void helpPanel_MouseEnter(object sender, EventArgs e)
        {
            PanelMouseEnter(helpPanel);
        }

        private void helpPanel_MouseLeave(object sender, EventArgs e)
        {
            helpPanel.BackColor = Properties.Settings.Default.BackColor;
        }

        private void aboutPanel_MouseEnter(object sender, EventArgs e)
        {
            PanelMouseEnter(aboutPanel);
        }

        private void aboutPanel_MouseLeave(object sender, EventArgs e)
        {
            aboutPanel.BackColor = Properties.Settings.Default.BackColor;
        }
        //----鼠标移过效果End----
        //----鼠标按下效果Start----
        private void PanelMouseDown(Panel panel, PictureBox pictureBox, Label label)
        {
            panel.Width = panel.Width - 2;
            panel.Height = panel.Height - 2;
            panel.Top = panel.Top + 1;
            panel.Left = panel.Left + 1;
            pictureBox.Top = pictureBox.Top - 1;
            pictureBox.Left = pictureBox.Left - 1;
            label.Top = label.Top - 1;
            label.Left = label.Left - 1;
        }

        private void PanelMouseUp(Panel panel, PictureBox pictureBox, Label label)
        {
            panel.Width = panel.Width + 2;
            panel.Height = panel.Height + 2;
            panel.Top = panel.Top - 1;
            panel.Left = panel.Left - 1;
            pictureBox.Top = pictureBox.Top + 1;
            pictureBox.Left = pictureBox.Left + 1;
            label.Top = label.Top + 1;
            label.Left = label.Left + 1;
        }
        //调用PanelMouseUp和PanelMouseDown
        private void startPanel_MouseDown(object sender, MouseEventArgs e)
        {
            PanelMouseDown(startPanel, startPictureBox, startLabel);
        }

        private void startPanel_MouseUp(object sender, MouseEventArgs e)
        {
            PanelMouseUp(startPanel, startPictureBox, startLabel);
        }

        private void settingsPanel_MouseDown(object sender, MouseEventArgs e)
        {
            PanelMouseDown(settingsPanel, settingsPictureBox, settingsLabel);
        }

        private void settingsPanel_MouseUp(object sender, MouseEventArgs e)
        {
            PanelMouseUp(settingsPanel, settingsPictureBox, settingsLabel);
        }

        private void backupPanel_MouseDown(object sender, MouseEventArgs e)
        {
            PanelMouseDown(backupPanel, backupPictureBox, backupLabel);
        }

        private void backupPanel_MouseUp(object sender, MouseEventArgs e)
        {
            PanelMouseUp(backupPanel, backupPictureBox, backupLabel);
        }

        private void viewPanel_MouseDown(object sender, MouseEventArgs e)
        {
            PanelMouseDown(viewPanel, viewPictureBox, viewLabel);
        }

        private void viewPanel_MouseUp(object sender, MouseEventArgs e)
        {
            PanelMouseUp(viewPanel, viewPictureBox, viewLabel);
        }

        private void helpPanel_MouseDown(object sender, MouseEventArgs e)
        {
            PanelMouseDown(helpPanel, helpPictureBox, helpLabel);
        }

        private void helpPanel_MouseUp(object sender, MouseEventArgs e)
        {
            PanelMouseUp(helpPanel, helpPictureBox, helpLabel);
        }

        private void aboutPanel_MouseDown(object sender, MouseEventArgs e)
        {
            PanelMouseDown(aboutPanel, aboutPictureBox, aboutLabel);
        }

        private void aboutPanel_MouseUp(object sender, MouseEventArgs e)
        {
            PanelMouseUp(aboutPanel, aboutPictureBox, aboutLabel);
        }
        //----鼠标按下效果End----
        //----窗体效果End----

        private void backupPanel_Click(object sender, EventArgs e)
        {
            Backup();
        }

        private void backupBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                //备份过程
                string backupName, year = Convert.ToString(DateTime.Now.Year),
                               month = Convert.ToString(DateTime.Now.Month),
                               day = Convert.ToString(DateTime.Now.Day),
                               hour = Convert.ToString(DateTime.Now.Hour),
                               minute = Convert.ToString(DateTime.Now.Minute),
                               second = Convert.ToString(DateTime.Now.Second);
                if (month.Length == 1) month = "0" + month;
                if (day.Length == 1) day = "0" + day;
                if (hour.Length == 1) hour = "0" + hour;
                if (minute.Length == 1) minute = "0" + minute;
                if (second.Length == 1) second = "0" + second;
                backupName = year + month + day + hour + minute + second;
                double count = 0;
                double all = Properties.Settings.Default.BackupDirectoryAddress.Count;
                foreach (string directoryName in Properties.Settings.Default.BackupDirectoryAddress)
                {
                    string gameName = directoryName.Replace(Properties.Settings.Default.SaveAddress, null);
                    string backupPath = Properties.Settings.Default.BackupAddress + backupName;
                    string zipPath = backupPath + "\\" + gameName + ".saves";
                    Directory.CreateDirectory(backupPath);
                    Compression.CompressFolder(directoryName, zipPath, Properties.Settings.Default.ZipLevel);
                    count++;
                    backupBackgroundWorker.ReportProgress(Convert.ToInt32(count / all * 50));
                }
                //更新MD5过程
                count = 0;
                Properties.Settings.Default.MD5.Clear();
                foreach (string directoryName in Properties.Settings.Default.BackupDirectoryAddress)
                {
                    DirectoryInfo directory = new DirectoryInfo(directoryName);
                    //遍历文件
                    foreach (FileInfo files in directory.GetFiles("*", SearchOption.AllDirectories))
                    {
                        //计算MD5
                        string fileName = files.FullName;
                        string md5 = "";
                        byte[] hashValue;
                        FileStream fileStream = null;
                        System.Security.Cryptography.MD5CryptoServiceProvider md5CSP = new System.Security.Cryptography.MD5CryptoServiceProvider();
                        fileStream = new FileStream(fileName.Replace("\"", ""), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                        hashValue = md5CSP.ComputeHash(fileStream);
                        fileStream.Close();
                        md5 = BitConverter.ToString(hashValue);
                        md5 = md5.Replace("-", "");
                        Properties.Settings.Default.MD5.Add("{" + fileName + "}" + md5);
                    }
                    count++;
                    backupBackgroundWorker.ReportProgress(Convert.ToInt32(50 + count / all * 50));
                }
                Properties.Settings.Default.Save();
            }
            catch (Exception ex)
            {
                notifyIcon.ShowBalloonTip(5000, "Minecraft 存档备份 - 备份时出现错误", ex.Message, ToolTipIcon.Error);
                HandlingErrors.Record(ex);
            }
        }

        private void backupBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            percentLabel.Text = Convert.ToInt32(e.ProgressPercentage) + "%";
            等待下一次备份0ToolStripMenuItem.Text = "正在备份(" + Convert.ToInt32(e.ProgressPercentage) + "%)";
        }

        private void backupBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                //启用按钮，显示状态
                backupLabel.Text = "立即备份";
                stateLabel.Text = "备份完成";
                percentLabel.Text = "100%";
                等待下一次备份0ToolStripMenuItem.Text = "备份完成(100%)";
                backupPanel.Enabled = true;
                //自动删除旧备份
                if (Properties.Settings.Default.AutomaticallyRemoveBackup)
                {
                    //按文件数删除
                    if (Properties.Settings.Default.AutomaticallyRemoveBackupByFilesNumber)
                    {
                        //获取所有备份文件
                        StringCollection backupList = new StringCollection();
                        string dirPath = Properties.Settings.Default.BackupAddress;
                        List<string> dirs = new List<string>(Directory.EnumerateDirectories(dirPath));
                        backupList.Clear();
                        foreach (string folder in dirs)
                        {
                            backupList.Add(folder);
                        }
                        //循环删除文件夹
                        while (backupList.Count > Properties.Settings.Default.MaxBackupFilesNumber)
                        {
                            //删除备份
                            if (Directory.Exists(backupList[0])) Directory.Delete(backupList[0], true);
                            //刷新数据
                            dirs = new List<string>(Directory.EnumerateDirectories(dirPath));
                            backupList.Clear();
                            foreach (string folder in dirs)
                            {
                                backupList.Add(folder);
                            }
                        }
                    }
                    //按文件大小删除
                    else
                    {
                        //获取所有备份文件
                        StringCollection backupList = new StringCollection();
                        string dirPath = Properties.Settings.Default.BackupAddress;
                        double directorySize = GetDirectorySize(dirPath);
                        Console.Write(directorySize);
                        List<string> dirs = new List<string>(Directory.EnumerateDirectories(dirPath));
                        backupList.Clear();
                        foreach (string folder in dirs)
                        {
                            backupList.Add(folder);
                        }
                        //循环删除文件夹
                        while (directorySize > Properties.Settings.Default.MaxBackupFileSize)
                        {
                            if (Directory.Exists(backupList[0])) Directory.Delete(backupList[0], true);
                            //刷新数据
                            dirs = new List<string>(Directory.EnumerateDirectories(dirPath));
                            backupList.Clear();
                            directorySize = GetDirectorySize(dirPath);
                            foreach (string folder in dirs)
                            {
                                backupList.Add(folder);
                            }
                        }
                    }
                }
                BackupIco.Hide();
            }
            catch (Exception ex)
            {
                notifyIcon.ShowBalloonTip(5000, "Minecraft 存档备份 - 备份时出现错误", ex.Message, ToolTipIcon.Error);
                HandlingErrors.Record(ex);
            }
        }

        private void settingsPanel_Click(object sender, EventArgs e)
        {
            Options Options = new Options(this);
            Options.Show();
        }

        private void automaticBackupTimer_Tick(object sender, EventArgs e)
        {
            if (Properties.Settings.Default.AutomaticBackup && Properties.Settings.Default.AutomaticBackupByTime && Properties.Settings.Default.AutomaticBackupIfChanged)
            {
                FindDifference();
            }
            else if (Properties.Settings.Default.AutomaticBackup && Properties.Settings.Default.AutomaticBackupByTime && !Properties.Settings.Default.AutomaticBackupIfChanged)
            {
                Backup();
            }
        }

        private void findDifferenceBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                fileChanged = false;
                int filesNumber = 0;//统计文件数量变量
                double count = 0;
                double all = Properties.Settings.Default.BackupDirectoryAddress.Count;
                foreach (string directoryName in Properties.Settings.Default.BackupDirectoryAddress)
                {
                    DirectoryInfo directory = new DirectoryInfo(directoryName);
                    //遍历文件
                    foreach (FileInfo files in directory.GetFiles("*", SearchOption.AllDirectories))
                    {
                        //计算MD5
                        string fileName = files.FullName;
                        string md5 = "";
                        byte[] hashValue;
                        FileStream fileStream = null;
                        System.Security.Cryptography.MD5CryptoServiceProvider md5CSP = new System.Security.Cryptography.MD5CryptoServiceProvider();
                        fileStream = new FileStream(fileName.Replace("\"", ""), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                        hashValue = md5CSP.ComputeHash(fileStream);
                        fileStream.Close();
                        md5 = BitConverter.ToString(hashValue);
                        md5 = md5.Replace("-", "");
                        //判断MD5是否和存储的相符
                        if (!Properties.Settings.Default.MD5.Contains("{" + fileName + "}" + md5)) fileChanged = true;
                        filesNumber++;
                    }
                    count++;
                    findDifferenceBackgroundWorker.ReportProgress(Convert.ToInt32(count / all * 100));
                }
                //判断文件数量是否改变
                if (filesNumber != Properties.Settings.Default.MD5.Count) fileChanged = true;
            }
            catch (Exception ex)
            {
                HandlingErrors.Record(ex);
                notifyIcon.ShowBalloonTip(5000, "Minecraft 存档备份 - 查找文件变化失败", ex.Message, ToolTipIcon.Error);
            }
        }

        private void findDifferenceBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            percentLabel.Text = Convert.ToInt32(e.ProgressPercentage) + "%";
            等待下一次备份0ToolStripMenuItem.Text = "正在查找文件变化(" + Convert.ToInt32(e.ProgressPercentage) + "%)";
        }

        private void findDifferenceBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //启用按钮，显示状态
            backupLabel.Text = "立即备份";
            percentLabel.Text = "100%";
            backupPanel.Enabled = true;
            BackupIco.Hide();
            //判断是否要备份
            if (fileChanged)
            {
                stateLabel.Text = "查找文件变化完成-有变化";
                等待下一次备份0ToolStripMenuItem.Text = "查找文件变化完成-有变化(100%)";
                Backup();
            }
            else
            {
                stateLabel.Text = "查找文件变化完成-无变化";
                等待下一次备份0ToolStripMenuItem.Text = "查找文件变化完成-无变化(100%)";
            }
        }

        private void viewPanel_Click(object sender, EventArgs e)
        {
            ViewBackups ViewBackup = new ViewBackups();
            ViewBackup.Show();
        }

        private void startPanel_Click(object sender, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(Properties.Settings.Default.GameAddress);
            }
            catch (Exception)
            {
                MessageBox.Show("您必须正确填写游戏地址才能打开游戏！" + Environment.NewLine + "请转到“设置-游戏地址”。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        private void 显示主界面MToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Main Main = new Main();
            Main.Show();
            notifyIcon.Dispose();
        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            Hide();
            if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 2)
            {
                notifyIcon.ShowBalloonTip(5000, "Minecraft 存档备份", "Minecraft 存档备份仍在运行，如需显示主窗口，请双击系统托盘里的钟表图标。", ToolTipIcon.Info);
            }
            else
            {
                notifyIcon.ShowBalloonTip(5000, "Minecraft 存档备份", "Minecraft 存档备份仍在运行，如需显示主窗口，请双击此图标。", ToolTipIcon.Info);
            }
        }

        private void 退出EToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.ExitThread();
        }

        private void helpPanel_Click(object sender, EventArgs e)
        {
            Help Help = new Help();
            Help.Show();
        }

        private void aboutPanel_Click(object sender, EventArgs e)
        {
            About About = new About();
            About.Show();
        }

        private void 自动备份AToolStripMenuItem_Click(object sender, EventArgs e)
        {
            自动备份AToolStripMenuItem.Checked = !自动备份AToolStripMenuItem.Checked;
            Properties.Settings.Default.AutomaticBackup = 自动备份AToolStripMenuItem.Checked;
            Properties.Settings.Default.Save();
            automaticBackupTimer.Enabled = Properties.Settings.Default.AutomaticBackupByTime && Properties.Settings.Default.AutomaticBackup;
        }
    }
}
